{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Python 3.6: Preserved Order of **kwargs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PEP468 was accepted into 3.6, and this means that the order in which keyword arguments are collected into `**kwargs` is now maintained.\n",
    "\n",
    "Why does that matter you ask?\n",
    "\n",
    "Well, how about a function that takes in kwargs and needs to build an ordered type based on the *order* of the kwargs. In the past you would have had to use some workaround (often using an ordered dict) instead of the far more convenient `**kwargs` approach."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let me show you what I mean:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Suppose we want to write a `namedtuple` factory of our own where we can specify default values:\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from collections import namedtuple\n",
    "\n",
    "def defaulted_namedtuple(class_name, **fields):\n",
    "    Struct = namedtuple(class_name, fields.keys())\n",
    "    Struct.__new__.__defaults__ = tuple(fields.values())\n",
    "    return Struct    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "Vector2D = defaulted_namedtuple('Vector2D', \n",
    "                                x1=None, y1=None,\n",
    "                                x2=None, y2=None,\n",
    "                                origin_x=0, origin_y=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('x1', 'y1', 'x2', 'y2', 'origin_x', 'origin_y')"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Vector2D._fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "v1 = Vector2D(10, 10, 20, 20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Vector2D(x1=10, y1=10, x2=20, y2=20, origin_x=0, origin_y=0)"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "v1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This only works if the order of the keyword arguments passed to the function is retained in the `fields` dictionary!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
